#pragma once

#include "Node.h"
#include "axisalignedbox.h"

namespace RenderSystem
{
	class Movable;
	class SceneManager;
	class Camera;
	class Renderer;

	class SceneNode
		: public Node
	{
	public:
		typedef std::vector<Movable*>			MovableObjects;
		typedef MovableObjects::iterator		ObjectIterator;
		typedef MovableObjects::const_iterator	ConstObjectIterator;

	public:
		SceneNode(SceneManager* pCreator);
		~SceneNode();

		//attach object manipulation
		virtual void AttachObject( Movable* pMovableObject );
		virtual uint32 GetAttachedObjectsCount(void) const;
		virtual Movable* GetAttachedObject( uint32 uObjIdx );
		virtual Movable* DetachObject( uint32 uObjIdx );
		virtual void DetachObject( Movable* obj );
		virtual void DetachAllObjects(void);

		//scene culling
		bool IsInSceneGraph(void) const { return m_bInGraph; }
		SceneManager* GetCreator(void) const { return m_pCreator; }

		void ShowBoundingBox(bool bShow);
		bool GetShowBoundingBox() const;

		virtual SceneNode* CreateChildSceneNode( const Common::Vector3& translate = Common::Vector3::ZERO,  const Common::Quaternion& rotate = Common::Quaternion::IDENTITY );
		SceneNode* GetParentSceneNode(void) const;
		
		virtual void SetVisible(bool visible, bool cascade = true);

		virtual void FindVisibleObjects( Camera* pCamera, Renderer* pRenderer, bool bIncludeChildren = true );

	protected:

		//interface node
		virtual Node* CreateChildImpl(void);

		virtual void _Update(bool updateChildren, bool parentHasChanged);
		virtual void _UpdateBounds(void);

		virtual const Common::AxisAlignedBox& _GetWorldAABB(void) const;

		virtual void UpdateFromParentImpl(void) const;

		virtual void SetParent(Node* pParent);

		virtual void SetInSceneGraph(bool inGraph);

	protected:
		/// can be different scene manager
		SceneManager* m_pCreator;
		/// All attached objects
		MovableObjects m_conMovableObjects;
		/// World-Axis aligned bounding box, updated only through _update
		Common::AxisAlignedBox m_WorldAABB;
		/// Is this node a current part of the scene graph?
		bool m_bInGraph;
		/// show aabb wireframe flag
		bool m_bShowAABBWireFrame;
	};
}